<?php

namespace App\Http\Services;

use App\Exceptions\ServiceException;
use App\Exceptions\ServiceExceptionConstant;
use App\Http\Repositories\Daos\Good\GoodsCycleDao;
use App\Http\Repositories\Daos\Good\GoodsDao;
use App\Http\Repositories\Daos\Order\OrderDao;
use App\Http\Requests\UserContext;
use App\Http\Traits\GlobalConstant;
use App\Util\Helper;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class OrderService extends BaseService
{
    protected $orderDao;
    protected $goodsDao;
    protected $cycleDao;

    public function __construct(OrderDao $orderDao, GoodsDao $goodsDao, GoodsCycleDao $goodsCycleDao)
    {
        $this->orderDao = $orderDao;
        $this->goodsDao = $goodsDao;
        $this->cycleDao = $goodsCycleDao;
    }

    public function lists(UserContext $userContext)
    {
        $userId    = $userContext->getId();
        $orderSn   = request('order_sn') ?? '';
        $status    = request('status');
        $condition = [
            'user_id' => $userId,
        ];
        if (!empty($orderSn)) {
            $condition[] = ['order_sn', 'like', '%' . $orderSn . '%'];
        }
        if (isset($status)) {
            $condition[] = ['status', $status];
        }
        $page   = request('pageNum') ?? 1;
        $size   = request('pageSize') ?? 10;
        $field  = ['*'];
        $offset = ($page * $size) - $size;
        $query  = $this->orderDao->getModel()->where($condition);
        $count  = $query->count();
        $list   = $query->orderBy('id', 'desc')->with(["cycleInfo" => function ($query) {
            return $query->select(['id', 'title']);
        }])->limit($size)->offset($offset)->get($field);
        if (!empty($list)) {
            foreach ($list as &$item) {
                $item['status_tip'] = self::showOrderStatusTip($item);
            }
            unset($item);
        }
        return compact("list", "count");
    }

    public function createOrder(UserContext $userContext)
    {
        $userId  = $userContext->getId();
        $goodsId = request('g_id') ?? 0;
        $qty     = request('qty') ?? 1;
        $coupon  = request('coupon') ?? '';
        $payType = request('pay_type') ?? 'wx';
        $cycle   = request('cycle') ?? '';
        if (empty($goodsId)) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('goods_invalid'));
        }
        $goodsInfo = $this->goodsDao->getOne(['id' => $goodsId, 'status' => 1]);
        if (!$goodsInfo) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('goods_invalid'));
        }
        if (empty($cycle)) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('请选择付款周期'));
        }
        if (!empty($coupon)) {
            $couponInfo = $this->userCouponDao->getOne(['user_id' => $userId, 'id' => $coupon, 'use' => 0, 'valid_time' => ['symbol' => '>=', 'val' => time()]]);
        }
        $cycleInfo = $this->cycleDao->getOne(['id' => $cycle, 'g_id' => $goodsId, 'status' => 1]);
        if (empty($cycleInfo)) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('付款周期不存在或无效'));
        }
        $priceReal  = $cycleInfo['price'];
        $priceTotal = bcmul($priceReal, $qty, 2);
        $payTotal   = $priceTotal;
        if (!empty($couponInfo)) {
            $payTotal = bcsub($payTotal, $couponInfo['coupon_money'], 2);
        }
        if (bccomp($payTotal, 0, 2) <= 0) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('实付款异常，交易失败'));
        }
        $orderSn   = Helper::sn(20, 1);
        $orderData = [
            'user_id'        => $userId,
            'order_sn'       => $orderSn,
            'goods_id'       => $goodsId,
            'cycle_id'       => $cycle,
            'price'          => Helper::yuanToCent($cycleInfo['price']),
            'price_rebate'   => $goodsInfo['rebate'] ?? 0,
            'price_real'     => Helper::yuanToCent($priceReal),
            'total_num'      => $qty,
            'price_total'    => Helper::yuanToCent($priceTotal),
            'pay_total'      => Helper::yuanToCent($payTotal),
            'status'         => 0,
            'pay_identifier' => '',
            'pay_type'       => $payType,
            'goods_snap'     => ['title' => $goodsInfo['name'], 'cycle' => $cycleInfo['title']]
        ];
        DB::beginTransaction();
        try {
            //创建订单
            $order = $this->orderDao->save($orderData);
            DB::commit();
        } catch (\Exception $exception) {
            DB::rollBack();
            Log::error('创建订单失败:' . $exception->getMessage());
            throw new ServiceException(ServiceExceptionConstant::getErrorData('order_create_failed'));
        }
        return [
            'order_sn' => $orderSn,
            'id'       => $order['id'],
        ];
    }

    public function orderDetail(UserContext $userContext)
    {
        $userId  = $userContext->getId();
        $orderSn = request('order_sn') ?? '';
        return $this->orderDao->getOne(['order_sn' => $orderSn, 'user_id' => $userId]);
    }


    public static function showOrderStatusTip($order)
    {

        if (!is_array($order)) {
            $order = $order->toArray();
        }
        if ($order['status'] == -1) {
            return '已取消';
        }
        if ($order['status'] == 0) {
            return '待支付';
        }
        if ($order['status'] == 1) {
            return '已完成';
        }
    }

    public function orderCancel(UserContext $userContext)
    {
        $userId  = $userContext->getId();
        $orderSn = request('order_sn') ?? '';
        if (empty($orderSn)) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('订单不存在'));
        }
        $orderInfo = $this->orderDao->getOne(['order_sn' => $orderSn, 'user_id' => $userId]);
        if (!$orderInfo) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('订单不存在'));
        }
        $orderInfo->status = -1;
        $orderInfo->save();
        return true;
    }

    public function orderCheck(UserContext $userContext)
    {
        $orderSn = request('sn') ?? '';
        $userId  = $userContext->getId();
        if (empty($orderSn)) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('订单错误'));
        }
        $orderInfo = $this->orderDao->getOne(['order_sn' => $orderSn, 'user_id' => $userId]);
        if (empty($orderInfo)) {
            throw new ServiceException(ServiceExceptionConstant::getErrorData('订单错误'));
        }
        return $orderInfo;
    }

}
